package demo5;

import com.google.common.collect.Lists;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.light.LightParameter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class LombokPsiAugmentProvider extends PsiAugmentProvider {
    @Override
    protected <Psi extends PsiElement> List<Psi> getAugments(PsiElement psiElement, Class<Psi> type) {
        final List<Psi> emptyResult = Collections.emptyList();

        if ((psiElement instanceof PsiClass) == false) {
            return emptyResult;
        }

        PsiClass psiClass = (PsiClass) psiElement;
        PsiAnnotation psiAnnotation = LombokPsiUtils.getAnnotation(psiClass, "com.dkd.test.anno.GetSet");
        if (psiAnnotation == null) {
            return emptyResult;
        }
        if (PsiMethod.class.isAssignableFrom(type)) {
            List<PsiField> fields = LombokPsiUtils.getFields(psiClass);
            if (!fields.isEmpty()) {
                List<PsiElement> psiElementList = new ArrayList<>();
                for (PsiField field : fields) {
                    PsiType psiType = field.getType();
                    PsiMethod getMethod = LombokPsiUtils.createCacheMethod(psiClass, getNewMethodName(field), null, psiType,field);
                    psiElementList.add(getMethod);
                    List<PsiParameter> parameterList = Lists.newArrayList();
                    LightParameter lightParameter = new LightParameter(field.getName(), psiType, psiClass);
                    parameterList.add(lightParameter);
                    PsiMethod setMethod = LombokPsiUtils.createCacheMethod(psiClass, setNewMethodName(field), parameterList, PsiType.VOID,field);
                    psiElementList.add(setMethod);

                }
                return (List<Psi>) psiElementList;
            }
        }
        return emptyResult;
    }

    public static boolean isBooleanType(PsiType psiType) {

        boolean isBooleanType = psiType.equals(PsiType.BOOLEAN);


        if (!isBooleanType) {
            if (psiType instanceof PsiClassType) {
                PsiClassType classType = (PsiClassType) psiType;
                PsiClass resolvedClass = classType.resolve();
                if (resolvedClass != null && "java.lang.Boolean".equalsIgnoreCase(resolvedClass.getQualifiedName())) {
                    isBooleanType = true;
                }
            }
        }

        return isBooleanType;
    }


    private static String getNewMethodName(PsiField field) {
        PsiType fieldType = field.getType();
        String name = field.getName();
        if (isBooleanType(fieldType)) {
            if (name.startsWith("is")) {
                return makeName(name.substring(2), "is");
            } else {
                return makeName(name, "is");
            }

        } else {
            String s = name.toString();
            return makeName(s, "get");
        }
    }

    private static String setNewMethodName(PsiField field) {
        PsiType type = field.getType();
        String name = field.getName();
        if (isBooleanType(type)) {
            if (name.startsWith("is")) {
                name = name.substring(2);
            }
            return makeName(name, "is");
        } else {
            if (name.startsWith("is")) {
                name = name.substring(2);
            }
            return makeName(name, "set");
        }
    }


    private static String makeName(String source, String prefix) {
        if (source.length() == 1) {
            return prefix + source.substring(0, 1).toUpperCase();
        } else {
            return prefix + source.substring(0, 1).toUpperCase() + source.substring(1);
        }
    }
}
